001 /* 002 * Copyright 2004-2005 The Apache Software Foundation 003 * Copyright 2005 Stephen McConnell 004 * 005 * Licensed under the Apache License, Version 2.0 (the "License"); 006 * you may not use this file except in compliance with the License. 007 * You may obtain a copy of the License at 008 * 009 * http://www.apache.org/licenses/LICENSE-2.0 010 * 011 * Unless required by applicable law or agreed to in writing, software 012 * distributed under the License is distributed on an "AS IS" BASIS, 013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 014 * See the License for the specific language governing permissions and 015 * limitations under the License. 016 */ 017 package net.dpml.cli.commandline; 018 019 import java.util.ArrayList; 020 import java.util.Collections; 021 import java.util.HashMap; 022 import java.util.Iterator; 023 import java.util.List; 024 import java.util.Map; 025 import java.util.Properties; 026 import java.util.Set; 027 028 import net.dpml.cli.Argument; 029 import net.dpml.cli.Option; 030 import net.dpml.cli.WriteableCommandLine; 031 import net.dpml.cli.resource.ResourceConstants; 032 import net.dpml.cli.resource.ResourceHelper; 033 034 /** 035 * A WriteableCommandLine implementation allowing Options to write their 036 * processed information to a CommandLine. 037 * 038 * @author <a href="http://www.dpml.net">Digital Product Meta Library</a> 039 * @version 1.0.0 040 */ 041 public class WriteableCommandLineImpl extends CommandLineImpl implements WriteableCommandLine 042 { 043 private final Properties m_properties = new Properties(); 044 private final List m_options = new ArrayList(); 045 private final Map m_nameToOption = new HashMap(); 046 private final Map m_values = new HashMap(); 047 private final Map m_switches = new HashMap(); 048 private final Map m_defaultValues = new HashMap(); 049 private final Map m_defaultSwitches = new HashMap(); 050 private final List m_normalised; 051 private final Set m_prefixes; 052 053 /** 054 * Creates a new WriteableCommandLineImpl rooted on the specified Option, to 055 * hold the parsed arguments. 056 * 057 * @param rootOption the CommandLine's root Option 058 * @param arguments the arguments this CommandLine represents 059 */ 060 public WriteableCommandLineImpl( 061 final Option rootOption, final List arguments ) 062 { 063 m_prefixes = rootOption.getPrefixes(); 064 m_normalised = arguments; 065 } 066 067 /** 068 * Add an option. 069 * @param option the option to add 070 */ 071 public void addOption( Option option ) 072 { 073 m_options.add( option ); 074 m_nameToOption.put( option.getPreferredName(), option ); 075 for( Iterator i = option.getTriggers().iterator(); i.hasNext();) 076 { 077 m_nameToOption.put( i.next(), option ); 078 } 079 } 080 081 /** 082 * Add an option. 083 * @param option the option to add 084 * @param value the option value 085 */ 086 public void addValue( final Option option, final Object value ) 087 { 088 if( option instanceof Argument ) 089 { 090 addOption( option ); 091 } 092 List valueList = (List) m_values.get( option ); 093 if( valueList == null ) 094 { 095 valueList = new ArrayList(); 096 m_values.put( option, valueList ); 097 } 098 valueList.add( value ); 099 } 100 101 /** 102 * Add a switch. 103 * @param option the option to add 104 * @param value the option value 105 */ 106 public void addSwitch( final Option option, final boolean value ) 107 { 108 addOption( option ); 109 if( m_switches.containsKey( option ) ) 110 { 111 throw new IllegalStateException( 112 ResourceHelper.getResourceHelper().getMessage( 113 ResourceConstants.SWITCH_ALREADY_SET ) ); 114 } 115 else 116 { 117 if( value ) 118 { 119 m_switches.put( option, Boolean.TRUE ); 120 } 121 else 122 { 123 m_switches.put( option, Boolean.FALSE ); 124 } 125 } 126 } 127 128 /** 129 * Detects the presence of an option in this CommandLine. 130 * 131 * @param option the Option to search for 132 * @return true iff the option is present 133 */ 134 public boolean hasOption( final Option option ) 135 { 136 return m_options.contains( option ); 137 } 138 139 /** 140 * Finds the Option with the specified trigger 141 * 142 * @param trigger the name of the option to retrieve 143 * @return the Option matching the trigger or null if none exists 144 */ 145 public Option getOption( final String trigger ) 146 { 147 return (Option) m_nameToOption.get( trigger ); 148 } 149 150 /** 151 * Retrieves the Argument values associated with the specified Option 152 * 153 * @param option the Option associated with the values 154 * @param defaultValues the result to return if no values are found 155 * @return a list of values or defaultValues if none are found 156 */ 157 public List getValues( final Option option, final List defaultValues ) 158 { 159 // First grab the command line values 160 List valueList = (List) m_values.get( option ); 161 162 // Secondly try the defaults supplied to the method 163 if( ( valueList == null ) || valueList.isEmpty() ) 164 { 165 valueList = defaultValues; 166 } 167 168 // Thirdly try the option's default values 169 if( ( valueList == null ) || valueList.isEmpty() ) 170 { 171 valueList = (List) m_defaultValues.get( option ); 172 } 173 174 // Finally use an empty list 175 if( valueList == null ) 176 { 177 valueList = Collections.EMPTY_LIST; 178 } 179 180 return valueList; 181 } 182 183 /** 184 * Retrieves the Boolean value associated with the specified Switch 185 * 186 * @param option the Option associated with the value 187 * @param defaultValue the Boolean to use if none match 188 * @return the Boolean associated with option or defaultValue if none exists 189 */ 190 public Boolean getSwitch( final Option option, final Boolean defaultValue ) 191 { 192 // First grab the command line values 193 Boolean bool = (Boolean) m_switches.get( option ); 194 195 // Secondly try the defaults supplied to the method 196 if( bool == null ) 197 { 198 bool = defaultValue; 199 } 200 201 // Thirdly try the option's default values 202 if( bool == null ) 203 { 204 bool = (Boolean) m_defaultSwitches.get( option ); 205 } 206 207 return bool; 208 } 209 210 /** 211 * Add a property to the commandline. 212 * @param property the property name 213 * @param value the property value 214 */ 215 public void addProperty( final String property, final String value ) 216 { 217 m_properties.setProperty( property, value ); 218 } 219 220 /** 221 * Retrieves the value associated with the specified property 222 * 223 * @param property the property name to lookup 224 * @param defaultValue the value to use if no other is found 225 * @return the value of the property or defaultValue 226 */ 227 public String getProperty( final String property, final String defaultValue ) 228 { 229 return m_properties.getProperty( property, defaultValue ); 230 } 231 232 /** 233 * Retrieves the set of all property names associated with this CommandLine 234 * 235 * @return a none null set of property names 236 */ 237 public Set getProperties() 238 { 239 return Collections.unmodifiableSet( m_properties.keySet() ); 240 } 241 242 /** 243 * Return true if the trigger argument looks like an option. 244 * @param trigger the trigger to evaluate 245 * @return true if the trigger looks like an option 246 */ 247 public boolean looksLikeOption( final String trigger ) 248 { 249 for( final Iterator i = m_prefixes.iterator(); i.hasNext();) 250 { 251 final String prefix = (String) i.next(); 252 if( trigger.startsWith( prefix ) ) 253 { 254 return true; 255 } 256 } 257 return false; 258 } 259 260 /** 261 * Return this commandline as a string. 262 * @return the string representation 263 */ 264 public String toString() 265 { 266 final StringBuffer buffer = new StringBuffer(); 267 // need to add group header 268 for( final Iterator i = m_normalised.iterator(); i.hasNext();) 269 { 270 final String arg = ( String ) i.next(); 271 if( arg.indexOf( ' ' ) >= 0 ) 272 { 273 buffer.append( "\"" ).append( arg ).append( "\"" ); 274 } 275 else 276 { 277 buffer.append( arg ); 278 } 279 if( i.hasNext() ) 280 { 281 buffer.append( ' ' ); 282 } 283 } 284 return buffer.toString(); 285 } 286 287 /** 288 * Retrieves a list of all Options found in this CommandLine 289 * 290 * @return a none null list of Options 291 */ 292 public List getOptions() 293 { 294 return Collections.unmodifiableList( m_options ); 295 } 296 297 /** 298 * Retrieves a list of all Option triggers found in this CommandLine 299 * 300 * @return a none null list of Option triggers 301 */ 302 public Set getOptionTriggers() 303 { 304 return Collections.unmodifiableSet( m_nameToOption.keySet() ); 305 } 306 307 /** 308 * Set default values. 309 * @param option the option 310 * @param defaults a list of defaults 311 */ 312 public void setDefaultValues( final Option option, final List defaults ) 313 { 314 if( defaults == null ) 315 { 316 m_defaultValues.remove( option ); 317 } 318 else 319 { 320 m_defaultValues.put( option, defaults ); 321 } 322 } 323 324 /** 325 * Set default switch. 326 * @param option the option 327 * @param defaultSwitch the default switch state 328 */ 329 public void setDefaultSwitch( final Option option, final Boolean defaultSwitch ) 330 { 331 if( defaultSwitch == null ) 332 { 333 m_defaultSwitches.remove( defaultSwitch ); 334 } 335 else 336 { 337 m_defaultSwitches.put( option, defaultSwitch ); 338 } 339 } 340 341 /** 342 * Return the normalized collection. 343 * @return the moprmalized collection 344 */ 345 public List getNormalised() 346 { 347 return Collections.unmodifiableList( m_normalised ); 348 } 349 }